﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Threading.Tasks;

namespace Dapper.Core
{
    /// <summary>
    /// 基础服务
    /// </summary>
    /// <typeparam name="T">实体类</typeparam>
    public class BaseServices<T> : IBaseServices<T> where T : class, new()
    {
        protected IBaseRepository<T> _repository;
        protected BaseServices(IBaseRepository<T> repository)
        {
            _repository = repository;
        }

        #region 基础同步方法

        /// <summary>
        /// 同步查询返回动态类型
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <param name="commandType"></param>
        /// <returns></returns>
        public T QueryFirstOrDefault(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            return _repository.QueryFirstOrDefault<T>(sql, param, transaction, commandTimeout, commandType);
        }

        /// <summary>
        /// 同步查询返回特定类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <param name="transaction"></param>
        /// <param name="buffered"></param>
        /// <param name="commandTimeout"></param>
        /// <param name="commandType"></param>
        /// <returns></returns>
        public IEnumerable<T> Query(string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
        {
            return _repository.Query<T>(sql, param, transaction, buffered, commandTimeout, commandType);
        }

        /// <summary>
        /// 同步执行命令
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <param name="commandType"></param>
        /// <returns></returns>
        public int Execute(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            return _repository.Execute(sql, param, transaction, commandTimeout, commandType);
        }

        /// <summary>
        /// 同步分页查询返回分页后的泛型集合
        /// </summary>
        /// <typeparam name="T">分页后的泛型集合</typeparam>
        /// <param name="sql">查询Sql语句或存储过程名称</param>
        /// <param name="param">参数值（可选）</param>
        /// <param name="transaction">事务名称（可选）</param>
        /// <param name="commandTimeout">超时时间（可选）</param>
        /// <param name="commandType">指定如果解释sql字符串：语句/存储过程（可选）</param>
        /// <returns>返回分页后的泛型集合</returns>
        public Tuple<IEnumerable<T>, int> QueryPage(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            return _repository.QueryPage<T>(sql, param, transaction, commandTimeout, commandType);
        }

        #endregion

        #region 基础异步方法

        /// <summary>
        /// 同步查询返回动态类型
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <param name="commandType"></param>
        /// <returns></returns>
        public async Task<T> QueryFirstOrDefaultAsync(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            return await _repository.QueryFirstOrDefaultAsync<T>(sql, param, transaction, commandTimeout, commandType);
        }

        /// <summary>
        /// 异步查询返回特定类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <param name="commandType"></param>
        /// <returns></returns>
        public async Task<IEnumerable<T>> QueryAsync(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            return await _repository.QueryAsync<T>(sql: sql, param, transaction, commandTimeout, commandType);
        }

        /// <summary>
        /// 异步执行命令
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <param name="commandType"></param>
        /// <returns></returns>
        public async Task<int> ExecuteAsync(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            return await _repository.ExecuteAsync(sql, param, transaction, commandTimeout, commandType);
        }

        /// <summary>
        /// 异步分页查询返回分页后的泛型集合
        /// </summary>
        /// <typeparam name="T">分页后的泛型集合</typeparam>
        /// <param name="sql">查询Sql语句或存储过程名称</param>
        /// <param name="param">参数值（可选）</param>
        /// <param name="transaction">事务名称（可选）</param>
        /// <param name="commandTimeout">超时时间（可选）</param>
        /// <param name="commandType">指定如果解释sql字符串：语句/存储过程（可选）</param>
        /// <returns>返回分页后的泛型集合</returns>
        public async Task<Tuple<IEnumerable<T>, int>> QueryPageAsync(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
        {
            return await _repository.QueryPageAsync<T>(sql, param, transaction, commandTimeout, commandType);
        }

        #endregion

        #region 扩展同步方法

        /// <summary>
        /// 同步获取一条
        /// </summary>
        /// <param name="id"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <returns></returns>
        public T Get(object id, IDbTransaction transaction = null, int? commandTimeout = null)
        {
            return _repository.Get(id, transaction, commandTimeout);
        }

        /// <summary>
        /// 同步获取所有实体
        /// </summary>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <returns></returns>
        public IEnumerable<T> GetAll(IDbTransaction transaction = null, int? commandTimeout = null)
        {
            return _repository.GetAll(transaction, commandTimeout);
        }

        /// <summary>
        /// 同步新增一条
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <returns></returns>
        public long Insert(T entity, IDbTransaction transaction = null, int? commandTimeout = null)
        {
            return _repository.Insert(entity, transaction, commandTimeout);
        }

        /// <summary>
        /// 同步新增多条
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <returns></returns>
        public long Insert(IEnumerable<T> entities, IDbTransaction transaction = null, int? commandTimeout = null)
        {
            return _repository.Insert(entities, transaction, commandTimeout);
        }

        /// <summary>
        /// 同步更新一条
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <returns></returns>
        public bool Update(T entity, IDbTransaction transaction = null, int? commandTimeout = null)
        {
            return _repository.Update(entity, transaction, commandTimeout);
        }

        /// <summary>
        /// 同步更新多条
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <returns></returns>
        public bool Update(IEnumerable<T> entities, IDbTransaction transaction = null, int? commandTimeout = null)
        {
            return _repository.Update(entities, transaction, commandTimeout);
        }

        /// <summary>
        /// 同步删除一条
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <returns></returns>
        public bool Delete(T entity, IDbTransaction transaction = null, int? commandTimeout = null)
        {
            return _repository.Delete(entity, transaction, commandTimeout);
        }

        /// <summary>
        /// 同步删除多条
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <returns></returns>
        public bool Delete(IEnumerable<T> entities, IDbTransaction transaction = null, int? commandTimeout = null)
        {
            return _repository.Delete(entities, transaction, commandTimeout);
        }

        #endregion

        #region 扩展异步方法

        /// <summary>
        /// 异步获取一条
        /// </summary>
        /// <param name="id"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <returns></returns>
        public async Task<T> GetAsync(object id, IDbTransaction transaction = null, int? commandTimeout = null)
        {
            return await _repository.GetAsync(id, transaction, commandTimeout);
        }

        /// <summary>
        /// 异步获取所有实体
        /// </summary>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <returns></returns>
        public async Task<IEnumerable<T>> GetAllAsync(IDbTransaction transaction = null, int? commandTimeout = null)
        {
            return await _repository.GetAllAsync(transaction, commandTimeout);
        }

        /// <summary>
        /// 异步新增一条
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <param name="sqlAdapter"></param>
        /// <returns></returns>
        public async Task<int> InsertAsync(T entity, IDbTransaction transaction = null, int? commandTimeout = null, ISqlAdapter sqlAdapter = null)
        {
            return await _repository.InsertAsync(entity, transaction, commandTimeout, sqlAdapter);
        }

        /// <summary>
        /// 异步新增多条
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <param name="sqlAdapter"></param>
        /// <returns></returns>
        public async Task<int> InsertAsync(IEnumerable<T> entities, IDbTransaction transaction = null, int? commandTimeout = null, ISqlAdapter sqlAdapter = null)
        {
            return await _repository.InsertAsync(entities, transaction, commandTimeout, sqlAdapter);
        }

        /// <summary>
        /// 异步更新一条
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <returns></returns>
        public async Task<bool> UpdateAsync(T entity, IDbTransaction transaction = null, int? commandTimeout = null)
        {
            return await _repository.UpdateAsync(entity, transaction, commandTimeout);
        }

        /// <summary>
        /// 异步更新多条
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <returns></returns>
        public async Task<bool> UpdateAsync(IEnumerable<T> entities, IDbTransaction transaction = null, int? commandTimeout = null)
        {
            return await _repository.UpdateAsync(entities, transaction, commandTimeout);
        }
        /// <summary>
        /// 异步删除一条
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <returns></returns>
        public async Task<bool> DeleteAsync(T entity, IDbTransaction transaction = null, int? commandTimeout = null)
        {
            return await _repository.DeleteAsync(entity, transaction, commandTimeout);
        }
        /// <summary>
        /// 异步删除多条
        /// </summary>
        /// <param name="entities"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <returns></returns>
        public async Task<bool> DeleteAsync(IEnumerable<T> entities, IDbTransaction transaction = null, int? commandTimeout = null)
        {
            return await _repository.DeleteAsync(entities, transaction, commandTimeout);
        }

        #endregion

        #region 扩展分页方法

        /// <summary>
        /// 同步根据条件查询数据库,并返回对象集合(用于分页数据显示)
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="fields">字段</param>
        /// <param name="condition">条件</param>
        /// <param name="info">分页实体</param>
        /// <param name="trans">事务对象</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <returns>指定对象的集合</returns>
        public List<T> GetPage(string tableName, string fields, string condition, PageParam info, IDbTransaction trans = null, int? commandTimeout = null)
        {
            return _repository.GetPage(tableName, fields, condition, info, trans, commandTimeout);
        }

        /// <summary>
        /// 异步根据条件查询数据库,并返回对象集合(用于分页数据显示)
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="fields">字段</param>
        /// <param name="condition">条件</param>
        /// <param name="info">分页实体</param>
        /// <param name="trans">事务对象</param>
        /// <param name="commandTimeout">超时时间</param>
        /// <returns>指定对象的集合</returns>
        public async Task<List<T>> GetPageAsync(string tableName, string fields, string condition, PageParam info, IDbTransaction trans = null, int? commandTimeout = null)
        {
            return await _repository.GetPageAsync(tableName, fields, condition, info, trans, commandTimeout);
        }

        #endregion
    }
}
